using System;
using System.Collections.Generic;
using Cinemachine;
using UnityEngine;
using UnityEngine.EventSystems;
using XLua;
using Yoozoo.HRP.Runtime;

public class PrettyGirlsFreedomCinemachineCamera : MonoBehaviour
{
    [SerializeField] private Camera m_useRealCamer;
    [SerializeField] private Transform m_theControlled;
    [SerializeField] private CharacterController m_cc;
    [SerializeField] private CinemachineVirtualCamera m_freedomCamera;
    [SerializeField] private Vector3 m_boxCenter = Vector3.zero;
    [SerializeField] private Vector3 m_boxSize = Vector3.zero;
    [SerializeField] private float m_moveSpeed = 5f;
    [SerializeField] private float m_rotateSpeed = 300f;
    [SerializeField] private float m_camerFovSpeed = 300f;
    [SerializeField] private float m_verticalRotateMax = 90f;
    [SerializeField] private float m_cameraMinFov = 25f;
    [SerializeField] private float m_cameraMaxFov = 60f;
    
    private Vector3 m_halfBoxSize = Vector3.zero;

    private Vector2 m_joystickDirection = Vector2.zero;
    private int m_verticalDirection = 0;
    private float m_fovScrollbarValue = -1f;

    private bool m_freedomModeState = false;

    private LuaFunction m_luaCallback;
    
    public List<string> m_excludedUIObjects = new List<string>()
    {
        "PrettyGirlsMainUI",
    }; // 需要排除的UI对象名称列表

    private PrettyGirlsVirtualJoystick m_joystick;
    
    private Touch m_screenTouch;

    private float m_lastRaycastTime = -1f; // 上次发射射线的时间
    private const float RAYCAST_COOLDOWN = 2f; // 射线冷却时间
    
    private HCamera baseCamera;
    private Quaternion baseCameraRotation;
    
    // Start is called before the first frame update
    void Start()
    {
        m_halfBoxSize = m_boxSize / 2;
        GetBaseCamera();
    }

    void GetBaseCamera()
    {
        // 这里需要通过find捕获节点 防止错误拿到其他场景相机 美女界面中BaseCamera只是占位的空相机
        if (baseCamera == null)
        {
            var go = GameObject.Find("BaseCamera");
            if (go)
            {
                baseCamera = go.GetComponent<HCamera>();
                baseCameraRotation = baseCamera.transform.rotation;
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (m_freedomModeState && m_theControlled != null && m_freedomCamera != null)
        {
            CalculateMoveDirection();
            CalculateRotateAmount();
            CalculateFovZoom();
        }
        GetBaseCamera();
        if (baseCamera != null && baseCamera.transform.rotation != m_useRealCamer.transform.rotation)
        {
            baseCamera.transform.rotation = m_useRealCamer.transform.rotation;
        }
    }

    private void CalculateMoveDirection()
    {
        Vector3 moveDirection = Vector3.zero;
        if (m_joystickDirection != Vector2.zero)
        {
            moveDirection += m_theControlled.forward * m_joystickDirection.y;
            moveDirection += m_theControlled.right * m_joystickDirection.x;
        }
#if UNITY_EDITOR
        else
        {
            if (Input.GetKey(KeyCode.W)) moveDirection += m_theControlled.forward;
            if (Input.GetKey(KeyCode.S)) moveDirection -= m_theControlled.forward;
            if (Input.GetKey(KeyCode.A)) moveDirection -= m_theControlled.right;
            if (Input.GetKey(KeyCode.D)) moveDirection += m_theControlled.right;
            if (Input.GetKey(KeyCode.Space)) moveDirection += Vector3.up;
            if (Input.GetKey(KeyCode.LeftControl)) moveDirection += Vector3.down;
        }
#endif
        if (m_verticalDirection != 0)
        {
            moveDirection += new Vector3(0, m_verticalDirection, 0);
        }

        if (moveDirection != Vector3.zero)
        {
            m_cc.Move(moveDirection * m_moveSpeed * Time.deltaTime);
            float xClamp = Mathf.Clamp(m_theControlled.position.x, m_boxCenter.x - m_halfBoxSize.x, m_boxCenter.x + m_halfBoxSize.x);
            float yClamp = Mathf.Clamp(m_theControlled.position.y, (m_boxCenter.y + transform.position.y) - m_halfBoxSize.y, (m_boxCenter.y + transform.position.y) + m_halfBoxSize.y);
            float zClamp = Mathf.Clamp(m_theControlled.position.z, m_boxCenter.z - m_halfBoxSize.z, m_boxCenter.z + m_halfBoxSize.z);
            m_theControlled.position = new Vector3(xClamp, yClamp, zClamp);
        }
    }

    private void CalculateRotateAmount()
    {
        bool bIsValidScreenTouch = false;
        if (Input.touchCount > 0)
        {
            Touch firstTouch = Input.GetTouch(0);
            // 1.第一个touch如果响应在UI范围内，那么就得拿第二个touch判断是否点击在空白屏幕出触发拖拽旋转
            // 2.摇杆脚本有按钮处于按压状态，还未抬起释放，在条件1中会判定为失败，因为不在范围内，但实际第一个touch还是在操作UI
            bool bIsTouchOnUI = IsPointerOverUIExceptExcluded(firstTouch) || m_joystick.IsPointerOnUI();
            if (bIsTouchOnUI)
            {
                if (Input.touchCount > 1)
                {
                    Touch secondTouch = Input.GetTouch(1);
                    // 检查第二根手指是否有效（不在UI上）
                    if (!IsPointerOverUIExceptExcluded(secondTouch))
                    {
                        bIsValidScreenTouch = true;
                        m_screenTouch = secondTouch;
                    }
                }
            }
            else
            {
                bIsValidScreenTouch = true;
                m_screenTouch = firstTouch;
            }
        }
        

        Vector2 mousePosition = Vector2.zero; // 用于做美女点击
        mousePosition.y = 99999;
        
        float mouseX = 0f;
        float mouseY = 0f;
        if (bIsValidScreenTouch)
        {
            if (m_screenTouch.phase == TouchPhase.Ended)
            {
                mousePosition = m_screenTouch.position;
            }
            else if (m_screenTouch.phase == TouchPhase.Moved)
            {
                mouseX = m_screenTouch.deltaPosition.x;
                mouseY = m_screenTouch.deltaPosition.y;
            }
        }
        
#if UNITY_EDITOR
        else if (Input.GetMouseButton(1))
        {
            mouseX = Input.GetAxis("Mouse X");
            mouseY = Input.GetAxis("Mouse Y");
        }
        else if (Input.GetMouseButtonUp(1))
        {
            mousePosition = Input.mousePosition;
        }
#endif


        if (mousePosition.y != 99999)
        {
            if (Time.time - m_lastRaycastTime >= RAYCAST_COOLDOWN)
            {
                Ray ray = m_useRealCamer.ScreenPointToRay(mousePosition);
                RaycastHit[] hits = Physics.RaycastAll(ray, Mathf.Infinity, LayerMask.GetMask("commander1"));
                Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance));
                foreach (var hit in hits)
                {
                    if (hit.collider.name.Equals("BabeClickTrigger"))
                    {
                        m_lastRaycastTime = Time.time;
                        m_luaCallback?.Action();
                        break;
                    }
                }
            }
        }

        if (mouseX != 0 || mouseY != 0)
        {
            Vector3 currentEulerAngles = m_theControlled.eulerAngles;
            float newVerticalAngle = currentEulerAngles.x - mouseY * m_rotateSpeed * Time.deltaTime;
            // 把欧拉角标准化为[-m_verticalRotateMax, m_verticalRotateMax]，实测Unity的欧拉角表示角度范围是[0, 360)，当角度超过180度时，x轴旋转实际上可能是负角度
            newVerticalAngle = newVerticalAngle > 180f ? newVerticalAngle - 360f : newVerticalAngle;
            newVerticalAngle = Mathf.Clamp(newVerticalAngle, -m_verticalRotateMax, m_verticalRotateMax);
            float newHorizontalAngle = currentEulerAngles.y + mouseX * m_rotateSpeed * Time.deltaTime;
            m_theControlled.rotation = Quaternion.Euler(newVerticalAngle, newHorizontalAngle, 0f);
            m_freedomCamera.transform.rotation = m_theControlled.rotation;
        }
    }

    private void CalculateFovZoom()
    {
        if (m_fovScrollbarValue != -1f)
        {
            m_freedomCamera.m_Lens.FieldOfView = m_cameraMinFov + m_fovScrollbarValue * (m_cameraMaxFov - m_cameraMinFov);
            m_fovScrollbarValue = -1f;
        }
#if UNITY_EDITOR
        else
        {
            float scrollInput = Input.GetAxis("Mouse ScrollWheel");
            if (scrollInput != 0)
            {
                float newCameraFov = m_freedomCamera.m_Lens.FieldOfView - scrollInput * m_camerFovSpeed * Time.deltaTime;
                m_freedomCamera.m_Lens.FieldOfView = Mathf.Clamp(newCameraFov, m_cameraMinFov, m_cameraMaxFov);
            }
        }
#endif
    }

    public bool IsPointerOverUIExceptExcluded(Touch touch)
    {
        PointerEventData pointerData = new PointerEventData(EventSystem.current)
        {
            position = touch.position
        };
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(pointerData, results);
        foreach (RaycastResult result in results)
        {
            if (!m_excludedUIObjects.Contains(result.gameObject.name))
            {
                return true;
            }
        }
        return false;
    }

    public void SetJoystickDirection(Vector2 joystickDirection)
    {
        m_joystickDirection = joystickDirection;
    }

    public void SetVerticalDirection(int verticalDirection)
    {
        m_verticalDirection = verticalDirection;
    }

    public void SetFovScrollbarValue(float sliderValue)
    {
        m_fovScrollbarValue = sliderValue;
    }

    public void SetArgs(float arg1, float arg2, float arg3, float arg4, float arg5, float arg6)
    {
        m_moveSpeed = arg1;
        m_rotateSpeed = arg2;
        m_camerFovSpeed = arg3;
        m_verticalRotateMax = arg4;
        m_cameraMinFov = arg5;
        m_cameraMaxFov = arg6;
    }
    
    public void SetFreedomModeState(bool state)
    {
        m_freedomModeState = state;
    }

    public void SetCcGameObject(GameObject ccGameObject)
    {
        m_theControlled = ccGameObject.transform;
        m_cc = ccGameObject.GetComponent<CharacterController>();
    }
    
    public void SetFreedomVirtualCamera(CinemachineVirtualCamera virtualCamera)
    {
        m_freedomCamera = virtualCamera;
    }

    public void SetJoystick(PrettyGirlsVirtualJoystick joystick)
    {
        m_joystick = joystick;
    }

    public void SetClickBabeCallback(LuaFunction luaCallback)
    {
        m_luaCallback = luaCallback;
    }

    private void OnDestroy()
    {
        if (baseCamera != null)
        {
            // 还原相机的角度
            baseCamera.transform.rotation = baseCameraRotation;
        }
    }

#if UNITY_EDITOR
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawWireCube(new Vector3(m_boxCenter.x, m_boxCenter.y + transform.position.y, m_boxCenter.z), m_boxSize);
    }
#endif
}